package com.haidechizi.util.async.advise;

import com.haidechizi.util.async.annotation.NonSync;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;

import java.util.concurrent.*;

/**
 * @author: wangdejun
 * @create: 2019-12-17 17:12
 **/
@Component
@Aspect
@Slf4j
@EnableAspectJAutoProxy
public class NonSyncAdvise {

    private final ThreadPoolExecutor executor = new ThreadPoolExecutor(5,
            10, 1, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100));

    @Pointcut("@annotation(nonSync)")
    public void pointCut(NonSync nonSync) {

    }

    @Around("pointCut(nonSync)")
    public Object around(ProceedingJoinPoint joinPoint, NonSync nonSync) throws Throwable {
        Future<Object> future = executor.submit(() -> {
            Object value = null;
            try {
                value = joinPoint.proceed();
            } catch (Throwable throwable) {
                log.error("执行出现异常：", throwable);
            }
            return value;
        });
        // 当大于0时，有超时时间
        if (nonSync.timeout() <= 0) {
            return future.get();
        } else {
            try {
                return future.get(nonSync.timeout(), nonSync.timeUnit());
            } catch (TimeoutException e) {
                log.error("执行超时：", e);
                // 任务执行超时时，取消正在执行的任务
                if (!future.isCancelled()) {
                    future.cancel(true);
                }
                return null;
            }
        }
    }
}
